feat: ts/packages/web-console, the browser client - #15
Merged
Conversation
Mearman
marked this pull request as ready for review
September 10, 2026 16:43
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
A client of any node, not just the hub: a browser-side Transport adapter implementing core's port over native WebSocket (one CBOR frame per binary message, the hub's convention; undecodable bytes reject the connection, unknown-but-decodable frames drop without disconnecting), and a DOM-free session module owning the client side of the handshake -- with an explicit unanswered state, since a relay-only node legitimately never answers one -- the gossip-derived peer directory, and the ordered frame log. The UI is deliberately thin DOM wiring over those. Builds to static assets with vite, servable from any origin. Verified against a locally-running hub (wrangler dev) using the same adapter and session modules the browser bundle imports: Node 26 provides the same native WebSocket, so the identical code path connected, observed the handshake go unanswered after the timeout, and recorded an outgoing ping. The room browser and join-from-browser UI are deferred and documented -- no node serves room semantics yet, and shipping dead UI for it would be dishonest.
Mearman
force-pushed
the
feat/web-console
branch
from
September 10, 2026 18:07
2199f0b to
278f7bc
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Plan task #7: the browser client — a client of any node, not just the hub, built to static assets (vite) and servable from any origin with no Cloudflare tie.
Architecture, same as its siblings: a browser-side Transport adapter (
src/adapters/websocket-transport.ts) implementing core's port over the browser's native WebSocket — the same one-CBOR-frame-per-binary-message convention the hub's Worker adapter speaks, with the same hostile-input split (undecodable bytes reject that connection; a decodable-but-unknown frame drops without disconnecting). A DOM-free session module (src/mesh-session.ts) owns everything with behaviour: the client side of the handshake exchange via core'snegotiate()— including an explicit unanswered state after a timeout, because a relay-only node like the hub legitimately never answers a handshake and that should be displayed, not treated as an error — the peer directory assembled from gossip frames (latest advert per device winning), and the ordered frame log.src/main.tsis deliberately thin DOM wiring.UI: connect form (node URL defaulting to the hub's
wrangler devport, domain checkboxes), negotiated-handshake status line, peer-directory table, live frame log with a send-ping button.Verified against a real running node:
wrangler devon the hub, then the actual adapter and session modules (the same code the browser bundle imports — Node 26 provides the identical native WebSocket) connected tows://localhost:8787:connecting → connected/pending → unansweredafter the timeout, outgoing ping recorded. Static bundle verified serving viavite preview(HTML + JS module 200). 18 unit tests cover the adapter's port semantics and the session's negotiation/directory/frame-log/rejection behaviour against fakes.Deferred, documented in the README: room browser / join-from-browser (no node serves room semantics yet — dead UI would be dishonest; the directory + frame inspector is the honest first pass), client identity (Web Crypto Identity adapter when a node requires one), and the live-hub e2e as a CI job (would couple console CI to a running workerd).